﻿using log4net;
using Mathmall.Administration.common;
using Mathmall.Administration.Mapper;
using Mathmall.Administration.Models;
using System.Text.Json;
using Microsoft.EntityFrameworkCore;

namespace Mathmall.Administration.Service.impl
{
    public class CategoryService : ICategoryService
    {
        private readonly CategoryMapper _categoryMapper;
        private readonly ICategoryBrandRelationService _categoryBrandRelationService;
        private static readonly ILog _logger = LogManager.GetLogger(typeof(UserService));

        public CategoryService(CategoryMapper categoryMapper,
            ICategoryBrandRelationService categoryBrandRelationService)
        {
            _categoryMapper = categoryMapper;
            _categoryBrandRelationService = categoryBrandRelationService;
        }

        /// <summary>
        /// 添加商品分类
        /// </summary>
        /// <param name="categoryVo">分类vo</param>
        /// <returns></returns>
        public async Task<int> AddCategory(CategoryVo categoryVo)
        {
            Category category = JsonSerializer.Deserialize<Category>(JsonSerializer.Serialize(categoryVo))!;

            return await _categoryMapper.AddCategory(category);
        }

        /// <summary>
        /// 根据父分类id，查询子分类信息集合
        /// <param name="parentCategoryId">父分类id</param>
        /// </summary>
        public List<CategoryVo> QueryCategoryVosByParentId(int? parentCategoryId)
        {
            List<CategoryVo> categoryVoLists = JsonSerializer.Deserialize<List<CategoryVo>>(
                JsonSerializer.Serialize(_categoryMapper.QueryCategoriesByParentId(parentCategoryId)))!;

            return categoryVoLists;
        }

        /// <summary>
        /// 分页查询
        /// </summary>
        /// <param name="pageNumber"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        public async Task<PaginatedList<CategoryVo>?> PaginatedQuery(int pageNumber, int pageSize)
        {
            // 查询全部符合条件的数据
            IQueryable<Category> categories = _categoryMapper.QueryAll();
            // 分页处理
            PaginatedList<Category> brandsPaginatedList =
                await PaginatedList<Category>.CreateAsync(categories, pageNumber, pageSize);
            List<CategoryVo> categoryVos = new List<CategoryVo>();
            // 通过序列化，将查到的数据放入VO中
            foreach (var item in brandsPaginatedList.Items)
            {
                CategoryVo categoryVo = JsonSerializer.Deserialize<CategoryVo>(JsonSerializer.Serialize(item))!;
                categoryVos.Add(categoryVo);
            }

            return new PaginatedList<CategoryVo>(categoryVos, brandsPaginatedList.Count, pageNumber, pageSize);
        }

        /// <summary>
        /// 查询所有分类，以树形结构返回
        /// </summary>
        public async Task<List<CategoryVo>> QueryAllCategories()
        {
            // 查询所有分类
            List<Category> categoryList = await _categoryMapper.QueryAll().ToListAsync();
            // 转换为vo
            List<CategoryVo> categoryVoList =
                JsonSerializer.Deserialize<List<CategoryVo>>(JsonSerializer.Serialize(categoryList))!;
            return BuildCategoryVoList(categoryVoList);
        }

        private List<CategoryVo> BuildCategoryVoList(List<CategoryVo> categoryVoList)
        {
            List<CategoryVo> finalNode = new List<CategoryVo>();
            // 遍历所有分类，得到顶级分类
            foreach (CategoryVo categoryVo in categoryVoList)
            {
                if (0 == categoryVo.ParentCID)
                {
                    // 根据顶级分类，递归查询
                    finalNode.Add(SelectChildren(categoryVo, categoryVoList));
                }
            }

            return finalNode;
        }

        private CategoryVo SelectChildren(CategoryVo parentVo, List<CategoryVo> categoryVoList)
        {
            foreach (CategoryVo categoryVo in categoryVoList)
            {
                // 根据父分类id，查询子分类
                if (parentVo.CategoryID == categoryVo.ParentCID)
                {
                    parentVo.Children.Add(SelectChildren(categoryVo, categoryVoList));
                }
            }

            return parentVo;
        }

        /// <summary>
        /// 更新分类信息
        /// </summary>
        /// <param name="categoryVo"></param>
        /// <returns></returns>
        public async Task<int> UpdateCategory(CategoryVo categoryVo)
        {
            Category category = JsonSerializer.Deserialize<Category>(JsonSerializer.Serialize(categoryVo))!;
            // 更新品牌与分类关系表中的分类名称字段
            _categoryBrandRelationService.UpdateCategoryName(categoryVo.CategoryID, categoryVo.Name);
            // 更新分类表
            return await _categoryMapper.UpdateCategory(category);
        }

        /// <summary>
        /// 删除分类信息
        /// </summary>
        /// <param name="categoryIdList"></param>
        /// <returns></returns>
        public async Task<int> DeleteCategories(List<int> categoryIdList)
        {
            return await _categoryMapper.DeleteCategories(categoryIdList);
        }

        /// <summary>
        /// 根据分类id查询分类的完整路径
        /// </summary>
        /// <param name="categoryID"></param>
        /// <returns></returns>
        public async Task<List<int>> GetCategoryIdPath(int categoryID)
        {
            // 拿到全部分类
            List<Category> categories = await _categoryMapper.GetAllCategories();

            // 开始查询
            List<int> ids = new List<int>();
            List<int> idPath = GetIdPath(categories, ids, categoryID);
            return idPath;
        }

        /// <summary>
        /// 递归查询分类id的完整路径
        /// </summary>
        /// <param name="categoryVoList"></param>
        /// <param name="idPath"></param>
        /// <param name="categoryID"></param>
        /// <returns></returns>
        private List<int> GetIdPath(List<Category> categoryVoList, List<int> idPath, int categoryID)
        {
            // 查询父id
            int parentId = (from category in categoryVoList
                where category.CategoryID == categoryID
                select category.ParentCID).FirstOrDefault();
            // 将父id放入集合作为最终返回结果
            idPath.Add(parentId);
            // 若父id为0，则说明查到顶级分类，结果查询
            if (parentId == 0)
            {
                return idPath;
            }

            return GetIdPath(categoryVoList, idPath, parentId);
        }

        /// <summary>
        /// 根据分类id查询分类信息
        /// </summary>
        /// <param name="categoryId"></param>
        /// <returns></returns>
        public async Task<Category> GetCategoryById(int categoryId)
        {
            return await _categoryMapper.GetCategoryById(categoryId);
        }

        /// <summary>
        /// 用循环返回树形结构
        /// </summary>
        /// <returns></returns>
        public async Task<List<CategoryVo>> GetAllCategoryVos()
        {
            // 查询全部数据
            List<Category> categories = await _categoryMapper.GetAllCategories();

            // 查询一级分类
            List<Category> levelOneList = categories.Where(category => category.ParentCID == 0).ToList();

            // 将一级分类放入vo
            List<CategoryVo>? finaNode =
                JsonSerializer.Deserialize<List<CategoryVo>>(JsonSerializer.Serialize(levelOneList))!;

            // 针对每个一级分类查询二级分类
            foreach (CategoryVo levelOneVo in finaNode)
            {
                List<Category> levelTwos =
                    categories.Where(category => category.ParentCID == levelOneVo.CategoryID).ToList();
                // 将每个二级分类放入一级分类的children中
                List<CategoryVo> levelTwoVos =
                    JsonSerializer.Deserialize<List<CategoryVo>>(JsonSerializer.Serialize(levelTwos))!;
                levelOneVo.Children.AddRange(levelTwoVos);
                
                // 针对每个二级分类查询三级分类
                foreach (CategoryVo levelTwoVo in levelTwoVos)
                {
                    List<Category> levelThrees = categories.Where(category => category.ParentCID == levelTwoVo.CategoryID).ToList()!;
                    // 将每个三级分类放入二级分类的children中
                    List<CategoryVo> levelThreeVos =
                        JsonSerializer.Deserialize<List<CategoryVo>>(JsonSerializer.Serialize(levelThrees))!;
                    levelTwoVo.Children.AddRange(levelThreeVos);
                }
            }
            return finaNode;
        }
    }
}